#include "lib/httplib.h"
#include "util.hh"
#include "data.hh"

#define BUSINESS_SUCC 1
#define BUSINESS_FAIL 0

namespace atm_server
{
    struct bus_result
    {
        bus_result(int code, const std::string& desc, const std::string& data)
            : code(code), desc(desc), data(data)
        {
        }

        int code;
        std::string desc;
        std::string data;

        std::string serialize()
        {
            Json::Value root;
            root["code"] = code;
            root["desc"] = desc;
            root["data"] = data;

            return json_util::serialize(root);
        }
    };

    struct business
    {
        static void balance(const httplib::Request& req, httplib::Response& rsp)
        {
            easylog::debug("balance body: {}", req.body);

            Json::Value root = json_util::deserialize(req.body);
            auto card_number = root["card_number"].asString();
            auto password = root["password"].asString();

            std::pair<double, bool> res = database::instance().balance(card_number, password);

            if (res.second)
            {
                Json::Value root;
                root["balance"] = res.first;
                std::string data = json_util::serialize(root);
                rsp.set_content(bus_result(BUSINESS_SUCC, "get balance success", data).serialize(), "application/json");
            }
            else
            {
                rsp.status = 400;
                rsp.set_content(bus_result(BUSINESS_FAIL, "get balance failed", "").serialize(), "application/json");
            }

        }

        static void deposit(const httplib::Request& req, httplib::Response& rsp)
        {
            easylog::debug("deposit body: {}", req.body);

            Json::Value root = json_util::deserialize(req.body);
            auto card_number = root["card_number"].asString();
            auto password = root["password"].asString();
            auto amount = root["amount"].asDouble();

            if (database::instance().deposit(card_number, password, amount))
            {
                rsp.set_content(bus_result(BUSINESS_SUCC, "deposit success", "").serialize(), "application/json");
            }
            else
            {
                rsp.status = 400;
                rsp.set_content(bus_result(BUSINESS_FAIL, "deposit failed", "").serialize(), "application/json");
            }
        }

        static void withdraw(const httplib::Request& req, httplib::Response& rsp)
        {
            easylog::debug("withdraw body: {}", req.body);

            Json::Value root = json_util::deserialize(req.body);
            auto card_number = root["card_number"].asString();
            auto password = root["password"].asString();
            auto amount = root["amount"].asDouble();

            if (database::instance().withdraw(card_number, password, amount))
            {
                rsp.set_content(bus_result(BUSINESS_SUCC, "withdraw success", "").serialize(), "application/json");
            }
            else
            {
                rsp.status = 400;
                rsp.set_content(bus_result(BUSINESS_FAIL, "withdraw failed", "").serialize(), "application/json");
            }
        }

        static void transfer(const httplib::Request& req, httplib::Response& rsp)
        {
            easylog::debug("transfer body: {}", req.body);

            Json::Value root = json_util::deserialize(req.body);
            auto card_number = root["card_number"].asString();
            auto password = root["password"].asString();
            auto to_card_number = root["target_card_number"].asString();
            auto amount = root["amount"].asDouble();

            if (database::instance().transfer(card_number, password, to_card_number, amount))
            {
                rsp.set_content(bus_result(BUSINESS_SUCC, "transfer success", "").serialize(), "application/json");
            }
            else
            {
                rsp.status = 400;
                rsp.set_content(bus_result(BUSINESS_FAIL, "transfer failed", "").serialize(), "application/json");
            }
        }

    };

}